package com.haojiang.mh.ui.fragment

import android.graphics.Color
import android.util.Log
import android.widget.TextView
import androidx.core.content.ContextCompat
import com.github.mikephil.charting.components.XAxis
import com.github.mikephil.charting.data.BarData
import com.github.mikephil.charting.data.BarDataSet
import com.github.mikephil.charting.data.BarEntry
import com.haojiang.mh.R
import com.haojiang.mh.cache.Const
import com.haojiang.mh.cache.MGlobal
import com.haojiang.mh.service.api.JsonCallback
import com.haojiang.mh.service.entity.*
import com.haojiang.mh.service.event.CardEvent
import com.haojiang.mh.service.event.ReportEvent
import com.haojiang.mh.ui.base.BaseActivity
import com.haojiang.mh.ui.base.BaseScrollAbleFragment
import com.haojiang.mh.utils.KLog
import com.haojiang.mh.utils.MUtil
import com.haojiang.mh.utils.SpUtil
import com.haojiang.mh.widget.TopTabLayout
import com.lzy.okgo.OkGo
import com.lzy.okgo.model.Response
import kotlinx.android.synthetic.main.fragment_day.*
import kotlinx.android.synthetic.main.fragment_week.*
import kotlinx.android.synthetic.main.fragment_week.item_body_move
import kotlinx.android.synthetic.main.fragment_week.item_body_revolve
import kotlinx.android.synthetic.main.fragment_week.item_breath_rate
import kotlinx.android.synthetic.main.fragment_week.item_heart_rate
import kotlinx.android.synthetic.main.fragment_week.item_intercept_count
import kotlinx.android.synthetic.main.fragment_week.item_score
import kotlinx.android.synthetic.main.fragment_week.item_snore_count
import kotlinx.android.synthetic.main.fragment_week.ttl_top_tab
import kotlinx.android.synthetic.main.fragment_week.tv_avg_sleep_cycle
import kotlinx.android.synthetic.main.fragment_week.tv_avg_sleep_time
import kotlinx.android.synthetic.main.fragment_week.wcc_sleep_cycle
import kotlinx.android.synthetic.main.fragment_week1.*
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import org.jetbrains.anko.appcompat.v7.Appcompat
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap

/**
 * 月报
 */
class WeekFragment : BaseScrollAbleFragment() {

    private var dayStart = ""
    private var dayEnd = ""
    private var isLeft = true
    private var bean: PeriodReportBean? = null

    override fun getLayoutId() = R.layout.fragment_week

    override fun initView() {
        item_score.init(getString(R.string.title_week_score), "")
        item_heart_rate.init(
            getString(R.string.text_heart_rate),
            getString(R.string.tv_heart_rate_unit)
        )
        item_breath_rate.init(getString(R.string.text_breath_rate), getString(R.string.tv_avg_unit))
        item_snore_count.init(
            getString(R.string.text_snore_count),
            getString(R.string.tv_body_unit_1)
        )
        item_intercept_count.init(
            getString(R.string.text_snore_intercept),
            getString(R.string.tv_body_unit_1)
        )
        item_body_move.init(
            getString(R.string.text_small_body_movement),
            getString(R.string.tv_body_unit_1)
        )
        item_body_revolve.init(
            getString(R.string.text_avg_body_cnt),
            getString(R.string.tv_body_unit_1)
        )
//        item_deep_sleep.init("深睡","分钟")

        ttl_top_tab.setOnTabSelectListener { selectTabIndex, _, flag ->
//            if (flag != TopTabLayout.SLIDE_END) return@setOnTabSelectListener
            isLeft = selectTabIndex == 0
            if (bean != null) {
                initAllChartView(bean!!)
            } else {
                getSelectWeekReport()
            }
        }
    }

    override fun onFragmentResume() {
        super.onFragmentResume()
        decideToGetWeekReport()
    }

    override fun onDestroyView() {
        OkGo.getInstance().cancelTag(this)
        super.onDestroyView()
    }

    //region 初始化所有图表
    /**
     * data一定不为null且不为空 否则就是数据出现问题 不做任何处理
     */
    private fun initAllChartView(bean: PeriodReportBean) {
        if (bean.data.isNullOrEmpty()) return
        calcCardInfoData(bean)
        val realList = ArrayList<SideBean>()
//        if (MGlobal.instance.currLeftSide) {//左边
        if (isLeft) {//左边
            for (info in bean.data!!) {
                if (info.value.left == null) {
                    val sb = SideBean()
                    sb.report_date = info.key
                    realList.add(sb)
                } else {
                    info.value.left!!.report_date = info.key
                    realList.add(info.value.left!!)
                }
            }
        } else {
            for (info in bean.data!!) {
                if (info.value.right == null) {
                    val sb = SideBean()
                    sb.report_date = info.key
                    realList.add(sb)
                } else {
                    info.value.right!!.report_date = info.key
                    realList.add(info.value.right!!)
                }
            }
        }
        //当realList为空说明当前是无数据的 需要更新View到NoData
        initSleepEvaluate(realList)
        initSleepTime(realList)
        initSleepCycle(realList)
        initSnoreIntervene(realList)
        initHeartInfo(realList)
        initBreathInfo(realList)
        initBodyMoveInfo(realList)
        initSleepBarChart(realList)
    }
    //endregion

    //region 计算卡片数据

    private fun calcCardInfoData(bean: PeriodReportBean) {
        if (bean.data.isNullOrEmpty()) return
        val leftList = ArrayList<SideBean>()
        val rightList = ArrayList<SideBean>()
        for (info in bean.data!!) {
            if (info.value.left != null) {
                leftList.add(info.value.left!!)
            }
            if (info.value.right != null) {
                rightList.add(info.value.right!!)
            }
        }
        val infoList = ArrayList<CardInfoBean>()
        //计算左侧数据
        val left = CardInfoBean()
        leftList.removeAll { it.score < 0 }
        if (leftList.isEmpty()) {
            left.score = -1
            left.evaluate = -1
        } else {
            var scoreL = 0
            var moveL = 0
            for (data in leftList) {
                scoreL += data.score
                moveL += data.body_move_times + data.body_revolve_times
            }
            left.score = Math.ceil(scoreL.toDouble() / leftList.size).toInt()
            left.evaluate = Math.ceil(moveL.toDouble() / leftList.size).toInt()
        }
        left.type = 1
        infoList.add(left)
        //计算右侧数据
        val right = CardInfoBean()
        rightList.removeAll { it.score < 0 }
        if (rightList.isEmpty()) {
            right.score = -1
            right.evaluate = -1
        } else {
            var scoreR = 0
            var moveR = 0
            for (data in rightList) {
                scoreR += data.score
                moveR += data.body_move_times + data.body_revolve_times
            }
            right.score = Math.ceil(scoreR.toDouble() / rightList.size).toInt()
            right.evaluate = Math.ceil(moveR.toDouble() / rightList.size).toInt()
        }
        right.type = 1
        infoList.add(right)
        EventBus.getDefault().post(CardEvent(infoList))
    }

    //endregion

    //region 睡眠评分图表相关
    private fun initSleepEvaluate(beanList: List<SideBean>) {
        if (beanList.isNullOrEmpty()) return
        var avgDay = 0
        var avgWork = 0
        var avgWeek = 0
        var sumCount = 0//计算次数
        var bigScoreBean = SideBean()
        val tempList = ArrayList<EvaluateBean>()
        for (data in beanList) {
            val eb = EvaluateBean()
            eb.date = data.report_date
            eb.score = data.score
            tempList.add(eb)
            if (bigScoreBean.score < data.score) {
                bigScoreBean = data
            }
            //以下计算平均得分
            if (data.score < 0) continue
            sumCount++
            avgDay += data.score
            if (MUtil.getWeek(data.report_date) in 1..5) {
                avgWork += data.score
            } else {
                avgWeek += data.score
            }
        }
        if (bigScoreBean.report_date.isNotEmpty()) {
            val day = bigScoreBean.report_date.substring(8)
            val week = MUtil.getWeekText(context, bigScoreBean.report_date)
//            tv_best_sleep_day.text = String.format(Locale.getDefault(), "%1s %2s", day, week)
        } else {
//            tv_best_sleep_day.text = "--"
        }
        /*ecv_week_fragment.setChartData(tempList)
        ecv_week_fragment.setOnScoreBallClickListener {
            val eventParam = java.util.HashMap<String, Any>()
            val strings = it.split("-".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
            var dayYear = Integer.parseInt(strings[0])
            var dayMonth = Integer.parseInt(strings[1])
            var dayDay = Integer.parseInt(strings[2])

            eventParam["year"] = dayYear
            eventParam["month"] = dayMonth
            eventParam["day"] = dayDay
            EventBus.getDefault().post(ReportEvent(Const.DAY_SWITCH, eventParam))
        }*/
        if (sumCount == 0) {
            avgDay = -1
            avgWork = -1
            avgWeek = -1
        } else {
            avgDay = Math.ceil(avgDay.toDouble() / sumCount).toInt()
            avgWork = Math.ceil(avgWork.toDouble() / sumCount).toInt()
            avgWeek = Math.ceil(avgWeek.toDouble() / sumCount).toInt()
        }
//        setFormatText(tv_avg_score, avgDay, 0)
        setFormatText(item_score.getText(), avgDay, 0)
//        setFormatText(tv_work_day_score, avgWork, 0)
//        setFormatText(tv_weekend_score, avgWeek, 0)
    }
    //endregion

    //region 睡眠时间分布
    private fun initSleepTime(beanList: List<SideBean>) {
        Log.e("TAG", "initSleepTime: ${beanList.size}")
        if (beanList.isNullOrEmpty()) return
        var sleepTime = 0
        var sumCount = 0
        val tempList = ArrayList<SleepTimeChartBean>()
        for (bean in beanList) {
            val stc = SleepTimeChartBean()
            stc.date = bean.report_date
            val sleepData = bean.sub_report?.get(0)?.sleep_data
            val tempLineList = ArrayList<StartEndBean>()
            if (sleepData != null) {
                for (data in sleepData) {
                    val ssb = StartEndBean()
                    ssb.setStart(MUtil.getHM(data.start))
                    ssb.setEnd(MUtil.getHM(data.end))
                    tempLineList.add(ssb)
                }
            }
            stc.line = tempLineList
            tempList.add(stc)
            if (bean.score < 0) continue
            sumCount++
            sleepTime = bean.sleep_time_hour * 60 + bean.sleep_time_minute
        }
        sleepTime = if (sumCount == 0) {
            -1
        } else {
            Math.ceil(sleepTime.toDouble() / sumCount).toInt()
        }
        setFormatText(tv_avg_sleep_time, sleepTime, 1)
//        stc_week_fragment.setChartData(tempList)
    }

    //新添加  睡眠时间柱形图
    private fun initSleepBarChart(beanList: List<SideBean>) {
        val list = ArrayList<BarEntry>()
        beanList.forEachIndexed { index, sideBean ->
            var hour = sideBean.sleep_time_hour.toFloat()
            if (hour < 0) {
                hour = 0f
            }
            list.add(BarEntry(index.toFloat(), hour))
        }
        val barDataSet = BarDataSet(list, "睡眠时长")
        barDataSet.color = R.color.color_golden_dark_n
        val barData = BarData(barDataSet)
//        barChart.setNoDataTextColor(ContextCompat.getColor(context, R.color.color_golden_dark_n))
        barChart.data = barData
        // 设置是否绘制背景
        barChart.setDrawGridBackground(false)
        //隐藏纵轴网格
        barChart.xAxis.setDrawAxisLine(false)
        //隐藏横轴网格
        barChart.axisLeft.setDrawGridLines(false)
        barChart.xAxis.setDrawGridLines(false)
        // 设置是否绘制边框
        barChart.setDrawBorders(false)
        // 设置是否可以缩放图表
        barChart.setScaleEnabled(true)
        // 设置是否可以用手指移动图表
        barChart.isDragEnabled = true
        barChart.description.isEnabled = false//隐藏右下角英文
        barChart.xAxis.position = XAxis.XAxisPosition.BOTTOM//X轴的位置 默认为上面
        barChart.axisRight.isEnabled = false//隐藏右侧Y轴   默认是左右两侧都有Y轴
    }
    //endregion

    //region 睡眠周期分布
    private fun initSleepCycle(beanList: List<SideBean>) {
        if (beanList.isNullOrEmpty()) return
        var sumCount = 0
        var avgDeep = 0
        var avgAwake = 0//新添加   卧床时间
        val tempList = ArrayList<SleepCycleChartBean>()
        for (bean in beanList) {
            val scc = SleepCycleChartBean()
            scc.date = bean.report_date
            val sdb = SleepDurationBean()
            val deep = bean.deep?.value ?: -1
            sdb.setDeep_duration_minute(if (deep < 0) "" else "$deep")
            val light = bean.light?.value ?: -1
            sdb.setLight_duration_minute(if (light < 0) "" else "$light")
            val rem = bean.deep?.value ?: -1
            sdb.setRem_duration_minute(if (rem < 0) "" else "$rem")
            val awake = bean.awake?.value ?: -1
            sdb.setAwake_duration_minute(if (awake < 0) "" else "$awake")
            scc.line = sdb
            tempList.add(scc)
            if (bean.score < 0) continue
            sumCount++
            avgDeep += bean.deep?.value ?: 0
            avgAwake += bean.awake?.value ?: 0
        }
        avgDeep = if (sumCount == 0) {
            -1
        } else {
            Math.ceil(avgDeep.toDouble() / sumCount).toInt()
        }
        avgAwake = if (sumCount == 0) {
            -1
        } else {
            Math.ceil(avgAwake.toDouble() / sumCount).toInt()
        }
        setFormatText(tv_avg_sleep_cycle, avgAwake, 1)
//        setFormatText(item_deep_sleep.getText(), avgDeep, 1)
        wcc_sleep_cycle.setChartData(tempList)
    }
    //endregion

    //region 打鼾⼲干预图表
    private fun initSnoreIntervene(beanList: List<SideBean>) {
        if (beanList.isNullOrEmpty()) return
        var sumSnore = 0
        var sumIntervene = 0
        var snore = 0
        var intervene = 0
        val tempList = ArrayList<TwoValueChartBean>()
        for (bean in beanList) {
            val tvc = TwoValueChartBean()
            tvc.date = bean.report_date
            val snoreList = bean.sub_report?.get(0)?.snore_count
            var snoreCount = 0
            if (!snoreList.isNullOrEmpty()) {
                for (s in snoreList) {
                    if (s.value > 0) snoreCount += s.value
                }
            }
            tvc.leftValue = snoreCount
            if (snoreCount != 0) {
                sumSnore++
                snore += snoreCount
            }
            val interveneList = bean.sub_report?.get(0)?.snore
            var interveneCount = 0
            if (!interveneList.isNullOrEmpty()) {
                for (i in interveneList) {
                    if (i.value > 0) interveneCount += i.value
                }
            }
            tvc.rightValue = interveneCount
            if (snoreCount != 0) {
                sumIntervene++
                intervene += interveneCount
            }
            tempList.add(tvc)
        }
        snore = if (sumSnore == 0) {
            -1
        } else {
            Math.ceil(snore.toDouble() / sumSnore).toInt()
        }
        intervene = if (sumIntervene == 0) {
            -1
        } else {
            Math.ceil(intervene.toDouble() / sumIntervene).toInt()
        }
//        setFormatText(tv_avg_snore_count, snore, 0)
        setFormatText(item_snore_count.getText(), snore, 0)
        setFormatText(item_intercept_count.getText(), intervene, 0)
//        wsc_snore.setTwoColumnData(tempList)
    }

    //endregion

    //region 心率图表
    private fun initHeartInfo(beanList: List<SideBean>) {
        if (beanList.isNullOrEmpty()) return
        var sumCount = 0
        var avgHeart = 0
        val tempList = ArrayList<MinMaxChartBean>()
        for (bean in beanList) {
            val mmc = MinMaxChartBean()
            mmc.date = bean.report_date
            val mmb = MinMaxBean()
            val item = bean.sub_report?.get(0)?.heart_beat
            if (item != null && !item.isNull()) {
                val temp = item.num!!.sorted() as MutableList<Int>
                temp.removeAll { it < 0 }
                mmb.min = temp[0]
                mmb.max = temp[temp.size - 1]
            }
            mmc.line = mmb
            tempList.add(mmc)
            val avg = bean.sub_report?.get(0)?.heart_beat_avg ?: -1
            if (avg > 0) {
                sumCount++
                avgHeart += avg
            }
        }
        avgHeart = if (sumCount == 0) {
            -1
        } else {
            Math.ceil(avgHeart.toDouble() / sumCount).toInt()
        }
//        setFormatText(tv_avg_heart_rate, avgHeart, 2)
        setFormatText(item_heart_rate.getText(), avgHeart, 2)
//        wsc_heart_rate.setRoundRectData(tempList)
    }
    //endregion

    //region 呼吸频率图表
    private fun initBreathInfo(beanList: List<SideBean>) {
        if (beanList.isNullOrEmpty()) return
        var sumCount = 0
        var avgBreath = 0
        val tempList = ArrayList<MinMaxChartBean>()
        for (bean in beanList) {
            val mmc = MinMaxChartBean()
            mmc.date = bean.report_date
            val mmb = MinMaxBean()
            val item = bean.sub_report?.get(0)?.breath
            if (item != null && !item.isNull()) {
                val temp = item.num!!.sorted() as MutableList<Int>
                temp.removeAll { it < 0 }
                mmb.min = temp[0]
                mmb.max = temp[temp.size - 1]
            }
            mmc.line = mmb
            tempList.add(mmc)
            val avg = bean.sub_report?.get(0)?.breath_avg ?: -1
            if (avg > 0) {
                sumCount++
                avgBreath += avg
            }
        }
        avgBreath = if (sumCount == 0) {
            -1
        } else {
            Math.ceil(avgBreath.toDouble() / sumCount).toInt()
        }
//        setFormatText(tv_avg_breath_rate, avgBreath, 2)
        setFormatText(item_breath_rate.getText(), avgBreath, 2)
//        wsc_breath_rate.setRoundRectData(tempList)
    }
    //endregion

    //region 体动图表
    private fun initBodyMoveInfo(beanList: List<SideBean>) {
        if (beanList.isNullOrEmpty()) return
        var sumMove = 0
        var sumIntervene = 0
        var avgMove = 0
        var avgIntervene = 0
        val tempList = ArrayList<TwoValueChartBean>()
        for (bean in beanList) {
            val tvc = TwoValueChartBean()
            tvc.date = bean.report_date
            tvc.leftValue = bean.body_move_times
            tvc.rightValue = bean.body_revolve_times
            tempList.add(tvc)
            if (bean.body_move_times > 0) {
                sumMove++
                avgMove += bean.body_move_times
            }
            if (bean.body_revolve_times > 0) {
                sumIntervene++
                avgIntervene += bean.body_revolve_times
            }
        }
        avgMove = if (sumMove == 0) {
            -1
        } else {
            Math.ceil(avgMove.toDouble() / sumMove).toInt()
        }
        avgIntervene = if (sumIntervene == 0) {
            -1
        } else {
            Math.ceil(avgIntervene.toDouble() / sumIntervene).toInt()
        }
//        setFormatText(tv_avg_body_move, avgMove, 3)
        setFormatText(item_body_move.getText(), avgMove, 3)
        setFormatText(item_body_revolve.getText(), avgIntervene, 3)
//        wsc_body_move.setTwoColumnData(tempList)
    }
    //endregion

    //region 公共方法

    /**
     * 设置文本
     */
    private fun setFormatText(tv: TextView, obj: Any, type: Int) {
        var text = ""
        val value = obj as Int
        when (type) {
            0 -> text = if (value < 0) "--" else "$value"
            1 -> {
                text = when {
                    value < 0 -> "--"
                    value >= 60 -> getString(R.string.tv_avg_sleep_duration, value / 60, value % 60)
                    else -> "$value ${getString(R.string.tv_sleep_unit)}"
                }
            }
            2 -> {
                text = if (value < 0) {
//                    "-- ${getString(R.string.tv_avg_unit)}"
                    "--"
                } else {
//                    "$value ${getString(R.string.tv_avg_unit)}"
                    "$value"
                }
            }
            3 -> {
                text = if (value < 0) {
//                    "-- ${getString(R.string.tv_body_unit_1)}"
                    "--"
                } else {
//                    "$value ${getString(R.string.tv_body_unit_1)}"
                    "$value"
                }
            }
        }
        tv.text = text
    }

    //endregion

    //region 接口数据

    /**
     * 根据设备MAC地址和是否需要更新Token,决定去获取报告
     */
    private fun decideToGetWeekReport() {
        if (SpUtil[Const.DEVICE_WIFI_MAC, ""].isEmpty()) {
            showToast(getString(R.string.text_no_device_tip))
            hideLoadingDialog()
        } else {
            context.showLoadingDialog()
            if (SpUtil.isNeedGetToken()) {
//                refreshToken()
                context.refreshToken(object : BaseActivity.OnRefreshTokenSuccessListener {
                    override fun onRefreshTokenSuccess() {
                        getSelectWeekReport()
                    }

                })
            } else {
                getSelectWeekReport()
            }
        }
    }

    /**
     * 获取日报
     */
    private fun getSelectWeekReport() {
        val url = Const.getReportList() + SpUtil[Const.DEVICE_WIFI_MAC, ""]
        val queryMap = HashMap<String, String>()
        queryMap["day_start"] = dayStart
        queryMap["day_end"] = dayEnd
        OkGo.get<PeriodReportBean>(url).tag(this).params(queryMap)
            .execute(object : JsonCallback<PeriodReportBean>() {

                override fun onNormalSuccess(response: Response<PeriodReportBean>) {
                    if (response.body().error.isEmpty()) {
                        KLog.d("数据正常") //TODO数据正常
                        bean = response.body().also {
                            initAllChartView(it)
                        }
                    } else {
                        showToast(getString(R.string.tip_get_data_fail))
                        KLog.e("getSelectMonthReport失败 response: $response")
                        when (response.body().error) {
                            "token_expired" -> KLog.e("Token 无效")
                        }
                    }
                }

                override fun onError(response: Response<PeriodReportBean>?) {
                    showToast(getString(R.string.tip_get_data_fail))
                    KLog.e("response: $response")
                }

                override fun onFinish() {
                    hideLoadingDialog()
                }
            })
    }

    /**
     * 刷新Token
     */
//    private fun refreshToken() {
//        val url = Const.getToken() + SpUtil[Const.DEVICE_WIFI_MAC, ""]
//        val queryMap = HashMap<String, String>()
//        queryMap["access_key"] = Const.ACCESS_KEY
//        queryMap["secret_key"] = Const.SECRET_KEY
//        OkGo.get<TokenBean>(url).tag(this).params(queryMap).execute(object : JsonCallback<TokenBean>() {
//
//            override fun onNormalSuccess(response: Response<TokenBean>) {
//                if (response.body().error.isEmpty()) {
//                    SpUtil.put(Const.TOKEN_LOCAL, response.body().data?.token ?: "")
//                    SpUtil.put(Const.TOKEN_EXIST_TIME, System.currentTimeMillis())
//                    getSelectWeekReport()
//                } else {
//                    hideLoadingDialog()
//                    KLog.e("Token 更新失败 response: $response")
//                    when (response.body().error) {
//                        "key_error" -> KLog.e("公私钥错误")
//                        "mac_error" -> KLog.e("MAC地址格式错误")
//                    }
//                }
//            }
//
//            override fun onError(response: Response<TokenBean>?) {
//                hideLoadingDialog()
//                KLog.e("Token 更新失败 response: $response")
//            }
//        })
//    }
    //endregion

    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    fun onReceiveEvent(event: ReportEvent) {
        if (event.type != Const.WEEK_OPERATE) return
        if (event.paramMap.isNullOrEmpty()) return
        val startYear = event.paramMap["startYear"] as Int
        val startMonth = event.paramMap["startMonth"] as Int
        val startDay = event.paramMap["startDay"] as Int
        val endYear = event.paramMap["endYear"] as Int
        val endMonth = event.paramMap["endMonth"] as Int
        val endDay = event.paramMap["endDay"] as Int
        dayStart =
            String.format(Locale.getDefault(), "%04d-%02d-%02d", startYear, startMonth, startDay)
        dayEnd = String.format(Locale.getDefault(), "%04d-%02d-%02d", endYear, endMonth, endDay)
        decideToGetWeekReport()
    }
}